/*//////////////////////////////////////////////////////////////////////////////
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//          Copyright(c) 2005-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"

#if defined (UMC_ENABLE_AAC_INT_AUDIO_DECODER)

#include <ipps.h>
#include <ippac.h>
#include <math.h>
#include <string.h>
#include "align.h"
#include "aaccmn_chmap.h"
#include "sbr_dec_struct.h"
#include "sbr_dec_api_int.h"
#include "sbr_dec_tabs_int.h"
#include "aac_dec_tns_int.h"
#include "sbr_dec_own_int.h"
#include "aac_dec_own_int.h"

/********************************************************************/

Ipp32s sbridecGetFilterSize(Ipp32s* pFilterSize)
{
  Ipp32s SizeSpecHQ;
  Ipp32s SizeSpecLP;
  IppStatus ippRes;

  /* -------------------------------- Analysis_SBR ---------------------------- */
  ippRes = ippsAnalysisFilterGetSize_SBRLP_32s(&SizeSpecLP);
  if (ippRes != ippStsOk)
    return 1;
  ippRes = ippsAnalysisFilterGetSize_SBRHQ_32s32sc(&SizeSpecHQ);
  if (ippRes != ippStsOk)
    return 1;

  pFilterSize[0] = MAX(SizeSpecLP, SizeSpecHQ);

  /* -------------------------------- Synthesis_SBR ---------------------------- */
  ippRes = ippsSynthesisFilterGetSize_SBRLP_32s(&SizeSpecLP);
  if (ippRes != ippStsOk)
    return 1;
  ippRes = ippsSynthesisFilterGetSize_SBRHQ_32sc32s(&SizeSpecHQ);
  if (ippRes != ippStsOk)
    return 1;

  pFilterSize[1] = MAX(SizeSpecLP, SizeSpecHQ);

  return 0;
}

/********************************************************************/

void sbridecDrawMemMap(sSbrDecFilter* pDC[CH_MAX], Ipp8u* pMem, Ipp32s* pSizes)
{
  Ipp32s i;

  for (i = 0; i < CH_MAX; i++){
    /* for Analysis */
    if (pSizes[0] != 0) {
      pDC[i]->pMemSpecQMFA[0] = pMem;
      pDC[i]->pMemSpecQMFA[1] = pMem + pSizes[0];
    } else {
      pDC[i]->pMemSpecQMFA[0] = NULL;
      pDC[i]->pMemSpecQMFA[1] = NULL;
    }
    pMem += pSizes[0] + pSizes[0];

    /* for Synthesis */
    if (pSizes[1] != 0) {
      pDC[i]->pMemSpecQMFS[0] = pMem;
      pDC[i]->pMemSpecQMFS[1] = pMem + pSizes[1];
    } else {
      pDC[i]->pMemSpecQMFS[0] = NULL;
      pDC[i]->pMemSpecQMFS[1] = NULL;
    }
    pMem += pSizes[1] + pSizes[1];
  }
}

/********************************************************************/

void sbridecUpdateMemMap(sSbrDecFilter* pDC[CH_MAX], Ipp32s mShift)
{
  Ipp32s i;

  for (i = 0; i < CH_MAX; i++){
    AACDEC_UPDATE_PTR(Ipp8u, pDC[i]->pMemSpecQMFA[0], mShift)
    AACDEC_UPDATE_PTR(Ipp8u, pDC[i]->pMemSpecQMFA[1], mShift)
    AACDEC_UPDATE_PTR(Ipp8u, pDC[i]->pMemSpecQMFS[0], mShift)
    AACDEC_UPDATE_PTR(Ipp8u, pDC[i]->pMemSpecQMFS[1], mShift)
  }
}

/********************************************************************/

Ipp32s sbridecInitFilter(AACDec *pState)
{
  Ipp32s i, j;
  IppStatus ippRes;
  sSbrDecFilter *pFilter;

  for (i = 0; i < CH_MAX; i++){
    pFilter = &(pState->sbr_filter[i]);
    for(j = 0; j < 2; j++){
      if (pState->com.ModeDecodeHEAACprofile == HEAAC_HQ_MODE) {
        ippRes = ippsAnalysisFilterInit_SBRHQ_32s32sc(
          (IppsFilterSpec_SBR_C_32sc *)(pFilter->pMemSpecQMFA[j]));
        if (ippRes != ippStsOk)
          return 1;
        ippRes =  ippsSynthesisFilterInit_SBRHQ_32sc32s(
          (IppsFilterSpec_SBR_C_32sc *)(pFilter->pMemSpecQMFS[j]));
        if (ippRes != ippStsOk)
          return 1;
      } else {
        ippRes = ippsAnalysisFilterInit_SBRLP_32s(
          (IppsFilterSpec_SBR_R_32s *)(pFilter->pMemSpecQMFA[j]));
        if (ippRes != ippStsOk)
          return 1;
        ippRes = ippsSynthesisFilterInit_SBRLP_32s(
          (IppsFilterSpec_SBR_R_32s *)(pFilter->pMemSpecQMFS[j]));
        if (ippRes != ippStsOk)
          return 1;
      }
    }
  }

  return 0;
}

/********************************************************************/

Ipp32s sbridecFreeFilter(sSbrDecFilter* pDC[CH_MAX])
{
  Ipp32s ch;

  if(pDC == NULL)
    return 0;

  for(ch = 0; ch < CH_MAX; ch++) {
    if(pDC[ch] != NULL)
      pDC[ch] = NULL;
  }
  return 0;
}
/********************************************************************/

Ipp32s sbri_ownAnalysisFilter_SBRHQ_32s_D2L(Ipp32s* pSrc,
                                            Ipp32sc* pDst[],
                                            Ipp32s nSubBand,
                                            Ipp32s kx,
                                            IppsFilterSpec_SBR_C_32sc* pFilterSpec)
{
  Ipp32s band;
  Ipp32s status = 0;

  for (band = 0; band < nSubBand; band++) {

    ippsAnalysisFilter_SBRHQ_32s32sc(pSrc + 32*band, pDst[band], kx, (IppsFilterSpec_SBR_C_32sc*) pFilterSpec);

  }

  return status;
}

/********************************************************************/

Ipp32s sbri_ownAnalysisFilter_SBRLP_32s_D2L(Ipp32s* pSrc,
                                            Ipp32s* pDstRe[],
                                            Ipp32s nSubBand,
                                            Ipp32s kx,
                                            IppsFilterSpec_SBR_R_32s* pFilterSpec)
{

  Ipp32s band;

  for (band=0; band<nSubBand; band++) {

    ippsAnalysisFilter_SBRLP_32s(pSrc + 32 * band, pDstRe[band], kx, (IppsFilterSpec_SBR_R_32s*) pFilterSpec);

  }

  return 0;
}

/********************************************************************/

Ipp32s sbriSynthesisFilter_32s(Ipp32s* bufZ, Ipp32s* pDst,
                               Ipp8u* pSpec,
                               Ipp32s* scaleFactor, Ipp32s mode)
{
  IppsFilterSpec_SBR_C_32sc* pSpecHQ = (IppsFilterSpec_SBR_C_32sc*)pSpec;
  IppsFilterSpec_SBR_R_32s*  pSpecLP = (IppsFilterSpec_SBR_R_32s*)pSpec;


  switch ( mode ) {

   case (HEAAC_HQ_MODE | HEAAC_DWNSMPL_OFF):

     ippsSynthesisFilter_SBRHQ_32sc32s( (Ipp32sc*)bufZ, pDst, pSpecHQ );

        *scaleFactor =  5 ;
        break;

   case (HEAAC_HQ_MODE | HEAAC_DWNSMPL_ON):

     ippsSynthesisDownFilter_SBRHQ_32sc32s( (Ipp32sc*)bufZ, pDst, pSpecHQ );

        *scaleFactor =  5 ;
        break;

   case (HEAAC_LP_MODE | HEAAC_DWNSMPL_OFF):

     ippsSynthesisFilter_SBRLP_32s(bufZ, pDst, pSpecLP );

      *scaleFactor =  4 ;
      break;

   case (HEAAC_LP_MODE | HEAAC_DWNSMPL_ON):
   default:

     ippsSynthesisDownFilter_SBRLP_32s(bufZ, pDst, pSpecLP );

      *scaleFactor =  4 ;
      break;
   }

  return 0; //OK
}

/********************************************************************/

#endif //UMC_ENABLE_AAC_INT_AUDIO_DECODER

